home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / vgacodng / part02.txt < prev    next >
Text File  |  1996-08-07  |  11KB  |  224 lines

  1.  
  2.                              VGA-Kurs - Part #2
  3.  
  4. Moin! Hier, nun und jetzt, wie zu erwarten "T.C.P.s' Beginner's Guide To VGA
  5. Coding"(TM), Part II!
  6. Wie schon im ersten Teil gesagt, werde ich diese Serie nur fortsetzen, wenn 
  7. sich auch genug Leute melden, mich mit Lob besudeln, mit Klagen zuballern
  8. oder mir einfach ein paar Tips geben.
  9. Na dann, aufi gaits Buam!
  10. Heute wollen wir uns einem wichtigen und für Anfänger oft sehr verwirrenden
  11. Kapitel der VGA-Programmierung zuwenden: Der VGA-Palette!
  12. Aber erst dies: Ihr erinnert euch doch bestimmt an unsere "optimierte"
  13. PutPixel-Routine aus der ersten Ausgabe; Sie schrieb die Pixelwerte direkt
  14. in den Bildschirmspeicher und war so bedeutend schneller als die
  15. Bios-Variante. Wollen mal sehen, ob wir nicht noch ein paar Clocks
  16. rausquetschen können:
  17.  
  18. procedure PutPixel(x,y:integer;
  19.                  col:byte);assembler;
  20. asm
  21.   mov     ax,0A000h
  22.   mov     es,ax
  23.   mov     bx,[x]
  24.   mov     dx,[y]
  25.   mov     di,bx
  26.   mov     bx,dx
  27.   shl     dx,8
  28.   shl     bx,6
  29.   add     dx,bx
  30.   add     di,dx
  31.   mov     al,[col]
  32.   stosb                          
  33. end;
  34.  
  35. (Hinweis: Für diese Prozedur müßt ihr entweder im Compiler-Optionsmenü die 
  36. 286er-Code Erzeugung aktivieren (oder am Anfang des Programms den
  37. Compiler-Schalter {$G+} setzen) oder statt "shl dx,8" 8 mal "shl dx" und 
  38. statt "shl bx,6" 6 mal "shl bx" schreiben.)
  39. Um den Sinn dieser Prozedur auf Anhieb zu verstehen, muß man schon etwas mehr
  40. Erfahrung haben: Als erstes wird (wie wahrscheinlich noch alle erkannt haben)
  41. die Adresse des VGA-Segments nach ES geMOVt (Manche werden wissen, daß das
  42. Register-Paar ES:DI einen Zeiger darstellt, und nun in DI das Offset des
  43. gewünschten Pixels stehen muß). Anschließend kommt die Adresse von x bzw. y
  44. nach BX bzw. DX. Nun wird (nachdem x nach BX nach DI und DX nach BX verschoben
  45. wurde, der Inhalt von DX (y) nun also in BX und DX ist) der Wert in DX um 8
  46. (entspricht einer Multiplikation mit 256) und der in BX um 6 (entspricht
  47. Mult. mit 64) nach links geshiftet. Dann werden die beiden addiert, und was
  48. haben wir jetzt? Y mult. mit 320! (Teuflisch, nicht?) Dazu wird nun der Wert
  49. von X addiert, dann die Farbe nach AL gebracht und STOSB aufgerufen. Schon
  50. haben wir den Pixel dort, wo wir ihn haben wollten!
  51. So, nun zu den Paletten. Wie wohl jeder weiß, hat man im Modus 13h 256 Farben
  52. zur Verfügung. Auswählen kann man diese 256 Farben aber aus einem Bereich von
  53. 262144 verschiedenen Farbtönen. Nun, die Standard-Auswahl ("Palette") der
  54. VGA-Farben ist nicht sehr klug gewählt und oft findet man die Farbe, die man
  55. braucht, nicht in dieser Auswahl. Also, wie beschafft man sich neue?
  56. Vorerst einmal ein paar Grundlagen (Ich weiß, Theorie ist Bullshit, aber sie
  57. muß trotzdem sein). Ihr habt bestimmt in der Schule mal gelernt, daß Farbtöne
  58. aus den drei Grundfarben entstehen: Rot, Grün (eigentlich Gelb) und Blau
  59. (Wenn nicht, wißt ihr es spätestens jetzt). Dadurch lassen sich theoretisch
  60. endlos viele Farben herstellen (die aber eigentlich niemand braucht ;-),
  61. indem man ebendiese Farben zu bestimmten Anteilen miteinander vermischt.
  62. Aber was hat das jetzt mit der VGA-Palette zu tun? Ganz einfach, sie basiert
  63. auf demselben Prinzip! Wenn man weiß wie, kann man sich über 260000 neue
  64. Farbtöne erstellen! Aber wie? Jede unserer 256 Standard-VGA-Farben besteht
  65. schon aus diesen 3 Farbwerten. Die Farbe 0 z.B. ist schwarz und besteht somit
  66. aus den Werten (0,0,0), also: 0 Rot, 0 Grün, 0 Blau. Farbe 31 dagegen (weiß)
  67. hat die Werte (63,63,63), also die Maximalwerte jedes Farbtons. So sind nun
  68. sämtliche Farben aufgebaut. Wenn man ein tiefes Blau hat (0,0,63), kann man
  69. es aufhellen, indem man die Werte für Rot und Grün heraufsetzt (32,32,63).
  70. Erhöht man dagegen nur den Wert für Rot, erhält man ein dunkleres Blau bis
  71. Lila.
  72. So, nun zum praktischen Teil: Wie setze ich die Palettenwerte einer Farbe?
  73.  
  74. procedure SetPal(col,R,G,B:byte);
  75. begin
  76.   port[$3C8] := col;
  77.   port[$3C9] := R;
  78.   port[$3C9] := G;
  79.   port[$3C9] := B;
  80. end;
  81.  
  82. Hier wird erst dem DAC-Port(3C8h) die Nummer der Farbe zugewiesen, um ihn auf 
  83. einen Schreibzugriff vorzubereiten. Anschließend werden die 3 Farbwerte an
  84. den Port 3C9h abgeschickt, und -zack!- sitzen die neuen Werte in der Palette.
  85. Dies ist sehr nützlich, weil alle Farben der Nummer col auf einen Schlag eine
  86. neue Farbe bekommen, was man trickreich ausnutzen kann. Ein Beißstiel: Die
  87. Palettenmanipulation wird oft in Adventures eingesetzt, wenn in einer Location
  88. ein Wasserfall simuliert werden soll. Dieser wird erst gezeichnet, und
  89. anschließend werden die Werte der Farben des Wasserfalls (meist Blautöne)
  90. ständig miteinander verstauscht, so daß es aussieht, als würde wirklich Wasser
  91. fließen. Aufwendige Animationen, die Speicherplatz verschwenden, bleiben einem
  92. erspart (Diese Methode nennt sich übrigens Colorcycling). Es gibt noch mehr
  93. Anwendungsbeispiele, von denen wir einige besprechen werden.
  94. Allerdings hat diese Pal-Manipulation einen Nachteil:
  95. Es entsteht ein Flackern, was nun wirklich unschön ist. Vermieden werden kann
  96. es, indem man vorher diese Prozedur callt:
  97.  
  98. procedure WaitRetrace;assembler;
  99. asm
  100.     mov     dx,3DAh
  101. @x: in      al,dx
  102.     test    al,08h
  103.     jnz     @x
  104. @y: in      al,dx
  105.     test    al,08h
  106.     jz      @y
  107. end;
  108.  
  109. Folgendes: Der Bildschirm wird alle soundsoviele Millisekunden wieder neu
  110. aufgebaut: "Retraced". Wird nun während eines solchen Retrace das Bild
  111. irgendwie verändert, so entsteht ein störendes Flackern. Dies kann vermieden
  112. werden, indem man vor JEDER wichtigen Bildschirmänderung (Sprite zeichnen,
  113. Palette verändern, etc.) den Retrace abwartet. Die Prozedur "weckt" das Input
  114. Status Register 1 der VGA und sieht nach, wie das Bit 3 aussieht. Es zeigt
  115. nämlich an, wie es um den Retrace steht. Die Prozedur wird solange geloopt,
  116. bis der Retrace unten am Bildschirm angelangt ist, dann beendet, worauf man
  117. die Palette verändern kann. Alles klar?
  118. Ach übrigens: Man kann die Palette auch auslesen:
  119.  
  120. procedure GetPal(col:byte;
  121.                  var R,G,B:byte);
  122. begin
  123.   port[$3C7] := col;
  124.   R := port[$3C9];
  125.   G := port[$3C9];
  126.   B := port[$3C9];
  127. end;
  128.  
  129. Mit dieser Prozedur kann man die Farbwerte der Farbe col ermitteln.
  130. So, war da nicht die Rede von anderen Anwendungsgebieten der Pal-Mod.?
  131. Hier etwas sehr trickreiches: Wenn man nicht will, daß der Anwender sieht,
  132. was man mit der VGA anstellt, kann man das auch "unsichtbar" machen. Man setzt
  133. einfach sämtliche Farben auf Schwarz:
  134.  
  135. procedure BlackPal;
  136. var n : byte;
  137. begin
  138.   WaitRetrace;
  139.   for n := 0 to 255 do
  140.     SetPal(n,0,0,0);
  141. end;
  142.  
  143. Allerdings sollte man vorher seine Palettenwerte sichern, sonst kann man das
  144. Bild schlecht wiederherstellen. Dazu deklarieren wir eine globale Variable
  145. Pal : array[0..255,1..3] of byte. Das Sichern der Palette:
  146.  
  147. procedure GrabPal;
  148. var n : byte;
  149. begin
  150.   for n := 0 to 255 do
  151.     GetPal(n,Pal[n,1],Pal[n,2],
  152.            Pal[n,3]);
  153. end;
  154.  
  155. Dies schreibt sämtliche Palettenwerte in das Array Pal. Wollen wir nun alle
  156. Werte wieder herstellen, brauchen wir eine neue Prozedur namens RestorePal,
  157. für die ihr einfach das GetPal in ein SetPal verwandelt und nach dem "begin"
  158. ein "waitretrace" einfügt.
  159. Nachdem man die Palette mit GrabPal gerettet, den Bildschirm mittels BlackPal
  160. abgedunkelt und das Bild (was auch immer das sein mag) auf den VGA
  161. "geklatscht" hat, kann man auch eine andere, effektvollere Art des
  162. Einblendens wählen, als einfach die Palette wiederherzustellen: Fading!
  163. Fading ist ein Paletteneffekt, den man sehr oft zu sehen bekommt. Er
  164. funktioniert folgendermaßen: Nachdem man die oben beschriebenen Schritte
  165. durchgeführt hat und der Bildschirm schwarz ist, schreibt man die gewünschte
  166. Zielpalette in die Variable Pal und erhöht nun solange schrittweise die 
  167. Palettenwerte, bis die Zielwerte in Pal erreicht sind. Das geht so:
  168.  
  169. procedure FadeUp;
  170. var n1,n2 : byte;
  171.     Tmp   : array[1..3] of byte;
  172. begin
  173.   for n1 := 1 to 64 do begin
  174.     WaitRetrace;
  175.     For n2 := 0 to 255 do begin
  176.       GetPal(n2,Tmp[1],Tmp[2],Tmp[3]);
  177.       if Tmp[1] < Pal[n2,1] then
  178.         inc (Tmp[1]);
  179.       if Tmp[2] < Pal[n2,2] then
  180.         inc (Tmp[2]);
  181.       if Tmp[3] < Pal[n2,3] then
  182.         inc (Tmp[3]);
  183.       SetPal(n2,Tmp[1],Tmp[2],Tmp[3]);
  184.     end;
  185.   end;
  186. end;
  187.  
  188. Bei dieser Prozedur wird zunächst der Retrace abgewartet. Anschließend wird
  189. für jede Farbe überprüft, ob ihre Farbwerte schon denen in der Zielpalette
  190. entsprechen. Wenn nicht, wird der Wert um 1 erhöht. Danach wird der neue
  191. Wert in die Palette eingetragen. Das Ganze wird 64 mal wiederholt.
  192. Umgekehrt geht auch. Will man also ein Bild auf dem VGA langsam ausfaden,
  193. schreibt man sich eine Prozedur wie oben, nur ersetzt man die INCs durch
  194. DECs, die Kleiner-als- durch Größer-als-Zeichen, und die "Pal[n2,?]" durch 0.
  195. So, nun können wir schon ein paar sehr schöne Effekte erzielen, vielleicht
  196. könnt ihr aus den vorgegebenen Routinen noch mehr machen (z.B ein Fading ins
  197. Weiße erzeugt den Eindruck einer Explosion). Ich hoffe ich werde in dem PCH,
  198. in dem diese Anzi erscheint schon eine Menge Feedback lesen.
  199. Nächstes Thema ist höchstwahrscheinlich...Scrollinx!!!
  200. Na dann, bis zur nächsten Ausgabe.
  201.  
  202.  
  203.  
  204.  
  205.  
  206. [ This text copyright (c) 1995-96 Johannes Spohr. All rights reserved. ]
  207. [ Distributed exclusively through PC-Heimwerker, Verlag Thomas Eberle. ]
  208. [                                                                      ]
  209. [ No  part   of  this   document  may  be   reproduced,   transmitted, ]
  210. [ transcribed,  stored in a  retrieval system,  or translated into any ]
  211. [ human or computer language, in any form or by any means; electronic, ]
  212. [ mechanical,  magnetic,  optical,   chemical,  manual  or  otherwise, ]
  213. [ without the expressed written permission of the author.              ]
  214. [                                                                      ]
  215. [ The information  contained in this text  is believed  to be correct. ]
  216. [ The text is subject to change  without notice and does not represent ]
  217. [ a commitment on the part of the author.                              ]
  218. [ The author does not make a  warranty of any kind with regard to this ]
  219. [ material, including,  but not limited to,  the implied warranties of ]
  220. [ merchantability  and fitness  for a particular  purpose.  The author ]
  221. [ shall not be liable for errors contained herein or for incidental or ]
  222. [ consequential damages in connection with the furnishing, performance ]
  223. [ or use of this material.                                             ]
  224.